package multi_thread.basic;

/**
 * @author Cheng Jun
 * Description:
 * join() 线程插队，join的底层是 调用 Object 的 wait方法，
 * 注意 join 方法被 synchronized 修饰，所以使用的是 线程实例的对象锁。
 * 注意 join 调用了 wait 方法不需要 programmer 主动调用 该线程实例的 notifyAll 方法，
 * 因为在该线程实例的run方法结束后，jvm 会调用 该线程实例的 notifyAll 方法，
 * 所以 join 里面产生 wait 方法会得到 线程实例的对象锁
 * @version 1.0
 * @date 2020/2/29 14:32
 */
public class JoinExample {

    public static void main(String[] args) {
        Thread thread1 = new Thread(() -> {
            try {
                Thread.sleep(2000);
                System.out.println(Thread.currentThread().getName() + "我睡了两秒，:D");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }, "子线程");
        thread1.start();
        System.out.println(Thread.currentThread() + "我是主线程！");

        // 哪个线程调用了join()方法，那就必须（无时间限制，一直死等下去）等那个线程运行结束，才能继续运行join下面的代码；
        // join方法本质是调用了Object的wait方法
        // try {
        //     thread1.join();
        // } catch (InterruptedException e) {
        //     e.printStackTrace();
        // }

        // 哪个线程调用了join(long millis)方法，那就（有时间限制，超过时间限制就不用等）等那个线程运行结束，才能继续运行join下面的代码；
        // 虽然join 的本质是 wait，但是 synchronized join 调用的是线程实例的wait，获取的线程实例thread1的锁，所以到了指定时间
        // 就会往下执行，这点和 WaitAndNotifyExample 里面 不一样，注意差别。
        try {
            thread1.join(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(thread1.getState());
    }
}
